//Wrapper for EE Math functions
#pragma once
#include "stdafx.h"

namespace EsenthelNet
{	
	///<summary>This static class contains helper operations for the EE Math functions.</summary>
	public ref class MathHelper abstract sealed {
	public:
		///<summary>PI/6 ( 30 deg)</summary>
		static PropGet(float, Pi_6, PI_6)
		///<summary>PI/4 ( 45 deg)</summary>
		static PropGet(float, Pi_4, PI_4)
		///<summary>PI/3 ( 60 deg)</summary>
		static PropGet(float, Pi_3, PI_3)
		///<summary>PI/2 ( 90 deg)</summary>
		static PropGet(float, Pi_2, PI_2)
		///<summary>PI   (180 deg)</summary>
		static PropGet(float, Pi, PI)
		///<summary>PI*2 (360 deg)</summary>
		static PropGet(float, Pi2, PI2)

		///<summary>Sqrt(2)</summary>
		static PropGet(float, Sqrt2, SQRT2)
		///<summary>Sqrt(3)</summary>
		static PropGet(float, Sqrt3, SQRT3)
		///<summary>Sqrt(2)/2</summary>
		static PropGet(float, Sqrt2_2, SQRT2_2)
		///<summary>Sqrt(3)/3</summary>
		static PropGet(float, Sqrt3_3, SQRT3_3)

		static int Min(int x, int y) { return EE::Min(x, y); }
		static unsigned int Min(unsigned int x, unsigned int y) { return EE::Min(x, y); }
		static float Min(float x, float y) { return EE::Min(x, y); }
		static double Min(double x, double y) { return EE::Min(x, y); }

		static int Max(int x, int y) { return EE::Max(x, y); }
		static float Max(float x, float y) { return EE::Max(x, y); }
		static double Max(double x, double y) { return EE::Max(x, y); }

		static int Min(int x, int y, int z) { return EE::Min(x, y, z); }
		static float Min(float x, float y, float z) { return EE::Min(x, y, z); }
		static double Min(double x, double y, double z) { return EE::Min(x, y, z); }

		static int Max(int x, int y, int z) { return EE::Max(x, y, z); }
		static float Max(float x, float y, float z) { return EE::Max(x, y, z); }
		static double Max(double x, double y, double z) { return EE::Max(x, y, z); }

		static int Min(int x, int y, int z, int w) { return EE::Min(x, y, z, w); }
		static float Min(float x, float y, float z, float w) { return EE::Min(x, y, z, w); }
		static double Min(double x, double y, double z, double w) { return EE::Min(x, y, z, w); }

		static int Max(int x, int y, int z, int w) { return EE::Max(x, y, z, w); }
		static float Max(float x, float y, float z, float w) { return EE::Max(x, y, z, w); }
		static double Max(double x, double y, double z, double w) { return EE::Max(x, y, z, w); }


		///<summary>Get middle value</summary>
		static int Mid(int x, int min, int max) { return EE::Mid(x, min, max); }
		///<summary>Get middle value</summary>
		static float Mid(float x, float min, float max) { return EE::Mid(x, min, max); }
		///<summary>Get middle value</summary>
		static double Mid(double x, double min, double max) { return EE::Mid(x, min, max); }

		///<summary>Get average value</summary>
		static float Avg(float x, float y) { return EE::Avg(x, y); }
		///<summary>Get average value</summary>
		static double Avg(double x, double y) { return EE::Avg(x, y); }
		///<summary>Get average value</summary>
		static float Avg(float x, float y, float z) { return EE::Avg(x, y, z); }
		///<summary>Get average value</summary>
		static double Avg(double x, double y, double z) { return EE::Avg(x, y, z); }
		///<summary>Get average value</summary>
		static float Avg(float x, float y, float z, float w) { return EE::Avg(x, y, z, w); }
		///<summary>Get average value</summary>
		static double Avg(double x, double y, double z, double w) { return EE::Avg(x, y, z, w); }

		///<summary>Faster version of "x less equal 0"</summary>
		static bool IsZeroNegative(float x) { return EE::ZeroNegative(x); }

		///<summary>Test if any of the parameters isn't zero.</summary>
		static bool Any(float x) { return EE::Any(x); }
		///<summary>Test if any of the parameters isn't zero.</summary>
		static bool Any(float x, float y) { return EE::Any(x, y); }
		///<summary>Test if any of the parameters isn't zero.</summary>
		static bool Any(float x, float y, float z) { return EE::Any(x, y, z); }
		///<summary>Test if any of the parameters isn't zero.</summary>
		static bool Any(float x, float y, float z, float w) { return EE::Any(x, y, z, w); }

		///<summary>Truncate</summary>
		static int Trunc(float x) { return EE::Trunc(x); }
		///<summary>Truncate</summary>
		static int Trunc(double x) { return EE::Trunc(x); }

		static int Round(float x) { return EE::Round(x); }
		static int Round(double x) { return EE::Round(x); }

		static int Floor(float x) { return EE::Floor(x); }
		static int Floor(double x) { return EE::Floor(x); }

		static int Ceil(float x) { return EE::Ceil(x); }
		static int Ceil(double x) { return EE::Ceil(x); }

		///<summary>Get fraction [0..1)</summary>
		static float Frac(float x) { return EE::Frac(x); }
		///<summary>Get fraction [0..1)</summary>
		static double Frac(double x) { return EE::Frac(x); }
		///<summary>Get fraction [-1..1) (sign preserving)</summary>
		static float FracS(float x) { return EE::FracS(x); }
		///<summary>Get fraction [-1	..1) (sign preserving)</summary>
		static double FracS(double x) { return EE::FracS(x); }

		///<summary>Get fraction [0..range)</summary>
		static float Frac(float x, float range) { return EE::Frac(x, range); }
		///<summary>Get fraction [0..range)</summary>
		static double Frac(double x, double range) { return EE::Frac(x, range); }
		///<summary>Get fraction [-range..range) (sign preserving)</summary>
		static float FracS(float x, float range) { return EE::FracS(x, range); }
		///<summary>Get fraction [-range	..range) (sign preserving)</summary>
		static double FracS(double x, double range) { return EE::FracS(x, range); }

		///<summary>Align 'x' to nearest multiple of 'align' using truncation</summary>
		static float AlignTrunc(float x, float align) { return EE::AlignTrunc(x, align); }
		///<summary>Align 'x' to nearest multiple of 'align' using rounding</summary>
		static float AlignRound(float x, float align) { return EE::AlignRound(x, align); }
		///<summary>Align 'x' to nearest multiple of 'align' using floor</summary>
		static float AlignFloor(float x, float align) { return EE::AlignFloor(x, align); }
		///<summary>Align 'x' to nearest multiple of 'align' using ceil</summary>
		static float AlignCeil(float x, float align) { return EE::AlignCeil(x, align); }
		///<summary>Align 'x' to nearest multiple of 'align' using truncation</summary>
		static double AlignTrunc(double x, double align) { return EE::AlignTrunc(x, align); }
		///<summary>Align 'x' to nearest multiple of 'align' using rounding</summary>
		static double AlignRound(double x, double align) { return EE::AlignRound(x, align); }
		///<summary>Align 'x' to nearest multiple of 'align' using floor</summary>
		static double AlignFloor(double x, double align) { return EE::AlignFloor(x, align); }
		///<summary>Align 'x' to nearest multiple of 'align' using ceil</summary>
		static double AlignCeil(double x, double align) { return EE::AlignCeil(x, align); }

		static EsenthelNet::Vec^ Min(EsenthelNet::Vec^ a, EsenthelNet::Vec^ b) { return gcnew EsenthelNet::Vec(Min(a->vec->x, b->vec->x), Min(a->vec->y, b->vec->y), Min(a->vec->z, b->vec->z)); }
		static EsenthelNet::Vec^ Max(EsenthelNet::Vec^ a, EsenthelNet::Vec^ b) { return gcnew EsenthelNet::Vec(Max(a->vec->x, b->vec->x), Max(a->vec->y, b->vec->y), Max(a->vec->z, b->vec->z)); }

		static EsenthelNet::Vec^ Avg(EsenthelNet::Vec^ a, EsenthelNet::Vec^ b) { return (a+b)*0.5f; }

		///<summary>Distance between two points.</summary>
		static float Dist(EsenthelNet::Vec^ a, EsenthelNet::Vec^ b) { return EE::Dist(*a->vec, *b->vec); }
		///<summary>Distance squared between two points.</summary>
		static float Dist2(EsenthelNet::Vec^ a, EsenthelNet::Vec^ b) { return EE::Dist2(*a->vec, *b->vec); }

		///<summary>Dot product</summary>
		static float Dot(EsenthelNet::Vec^ a, EsenthelNet::Vec^ b) { return EE::Dot(*a->vec, *b->vec); }
		///<summary>Cross product</summary>
		static EsenthelNet::Vec^ Cross(EsenthelNet::Vec^ a, EsenthelNet::Vec^ b) { return gcnew EsenthelNet::Vec(EE::Cross(*a->vec, *b->vec)); }
		///<summary>Cross product normalized</summary>
		static EsenthelNet::Vec^ CrossN(EsenthelNet::Vec^ a, EsenthelNet::Vec^ b) { return gcnew EsenthelNet::Vec(EE::CrossN(*a->vec, *b->vec)); }
		///<summary>Perpendicular vector</summary>
		static EsenthelNet::Vec^ Perp(EsenthelNet::Vec^ a) { return gcnew EsenthelNet::Vec(EE::Perp(*a->vec)); }
		///<summary>Perpendicular vector normalized</summary>
		static EsenthelNet::Vec^ PerpN(EsenthelNet::Vec^ a) { return gcnew EsenthelNet::Vec(EE::PerpN(*a->vec)); }
		///<summary>Reflect vector (result is on the same side of the plane)</summary>
		static EsenthelNet::Vec^ Reflect(EsenthelNet::Vec^ vec, EsenthelNet::Vec^ normal) { return gcnew EsenthelNet::Vec(EE::Reflect(*vec->vec, *normal->vec)); }
		///<summary>Reflect vector (result is on the same side of the plane)</summary>
		static EsenthelNet::Vec^ Reflect(EsenthelNet::Vec^ vec, EsenthelNet::Vec^ normal, EsenthelNet::Vec^ plane) { return gcnew EsenthelNet::Vec(EE::Reflect(*vec->vec, *plane->vec, *normal->vec)); }
		///<summary>Mirror vector (result is on the other side of the plane)</summary>
		static EsenthelNet::Vec^ Mirror(EsenthelNet::Vec^ vec, EsenthelNet::Vec^ normal) { return gcnew EsenthelNet::Vec(EE::Mirror(*vec->vec, *normal->vec)); }
		///<summary>Mirror vector (result is on the other side of the plane)</summary>
		static EsenthelNet::Vec^ Mirror(EsenthelNet::Vec^ vec, EsenthelNet::Vec^ normal, EsenthelNet::Vec^ plane) { return gcnew EsenthelNet::Vec(EE::Mirror(*vec->vec, *plane->vec, *normal->vec)); }

		static bool Equal(float r0, float r1) { return EE::Equal(r0, r1); }
		static bool Equal(double r0, double r1) { return EE::Equal(r0, r1); }
		static bool Equal(float r0, float r1, float eps) { return EE::Equal(r0, r1, eps); }
		static bool Equal(double r0, double r1, double eps) { return EE::Equal(r0, r1, eps); }
		static bool Equal(EsenthelNet::Vec^ v0, EsenthelNet::Vec^ v1) { return EE::Equal(*v0->vec, *v1->vec); }
		static bool Equal(EsenthelNet::Vec^ v0, EsenthelNet::Vec^ v1, float eps) { return EE::Equal(*v0->vec, *v1->vec, eps); }

		static int Compare(EsenthelNet::Vec^ v0, EsenthelNet::Vec^ v1) { return EE::Compare(*v0->vec, *v1->vec); }

	};
}